-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
crdutil: Add feature to also apply single files #58
base: main
Are you sure you want to change the base?
Conversation
Pull Request Test Coverage Report for Build 12053812919Details
💛 - Coveralls |
56fdeb6
to
e8a0806
Compare
e8a0806
to
7b4a23b
Compare
43b027c
to
776bbdb
Compare
Tanks for the extensive review @shivamerla. I should have implemented all findings in this diff.
|
4cd95ea
to
e72a10f
Compare
e72a10f
to
92553f3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM overall, just one comment on the linter stuff.
return nil | ||
} | ||
// If not recursive we want to only apply the CRDs in the top-level directory. | ||
if !recursive && parentDir.IsDir() && filepath.Dir(path) != strings.TrimRight(crdDir, "/") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we add a test case for this new branch or should these all be included in the "TODO add unit tests" comment you have added?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me take another look at the tests, I think I can easily test the walkCRDs
func
@@ -49,26 +51,32 @@ func (s *StringList) Set(value string) error { | |||
} | |||
|
|||
var ( | |||
crdsDir StringList | |||
files []string | |||
recursive bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it make sense to separate the handling of multiple non-recursive paths (including files) from the addition of recursive handling?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK kubectl
is also not separating it, so it is totally fine to keep it pretty open IMO. But also fine to me to split it somehow (you mean like: if multiple files are passed the recursive flag is not possible?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually just meant as separate PRs. From NVIDIA/gpu-operator#1137 it seems that we don't use recursive mode. Is it used in the network operator?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it is not used by the network-operator. Maybe it makes sense to remove this new feature from the PR, you are right. The request adding it to this PR came through #58 (comment) (at least that's how I understood it)
pkg/crdutil/crdutil.go
Outdated
log.Fatalf("CRDs directory is required") | ||
pflag.CommandLine.AddGoFlagSet(flag.CommandLine) | ||
pflag.StringSliceVarP(&files, "filename", "f", files, | ||
"The files that contain the configurations to apply.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This usage string does not seem to accurately represent the intent of the argument(s). From the PR description, I assume that each filename
represents a path. Each of these can be a directory or a YAML file path. For directories, the YAML files in the directory are processed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The flag names, the logic and also the description is copied from kubectl apply
:)
This does not mean that it's perfect, it's just already kind of Kubernetes native
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But to explain this a bit more:
- the old behavior was indeed recursive by default, but without the possibility to decide this
- the new behavior only handles yaml files in the same directory, if a directory is passed
- with setting the recursive flag all directories will be handled recursively
Let me add tests for this to make this pattern clear
pkg/crdutil/crdutil.go
Outdated
pflag.StringSliceVarP(&files, "filename", "f", files, | ||
"The files that contain the configurations to apply.") | ||
pflag.BoolVarP(&recursive, "recursive", "R", false, | ||
"Process the directory used in -f, --filename recursively. Useful when you want to manage related manifests organized within the same directory.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this not already handled without the -R
flag? (This was the previous behaviour).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as #58 (comment)
) | ||
|
||
func initFlags() { | ||
flag.Var(&crdsDir, "crds-dir", "Path to the directory containing the CRD manifests") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we concerned about this as a breaking change since the command line arguments are changed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was also thinking about this but this pkg is pretty new and we are only using it for the network-operator currently. Do you think we should deprecate it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the network-operator is not released with this change, better to just update as it will be first use of this package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The network-operator 24.10.0 has been released 2 days ago with the change in it, see https://github.com/Mellanox/network-operator/blob/v24.10.0/deployment/network-operator/templates/upgrade-crd-hook.yaml#L84.
But IMO it is totally fine to change it, because it is a Helm pre-install hook. If it fails, it fails the installation/upgrade and the user has to use the latest Helm chart. There is no dependency to the runtime which can cause the operator to fail.
tl;dr: this PR changes the flag --crds-dir
to --filename/-f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there is a concern, we could support both -- marking crds-dir
as deprecated -- for a release. Happy with the change since this is effectively an internal API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can also revert it to --crds-dir
. Both crds-dir
and filename
does not contain both files and dirs, so it is not 100% explicit anyway :)
Request came through #58 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shivamerla WDYT? Should we remove the flag rename and recursive flag (see #58 (comment)) out of this PR and change it in a follow-up? I'd say this will reduce the size of this PR.
pkg/crdutil/crdutil.go
Outdated
func walkCrdsDir(ctx context.Context, crdClient v1.CustomResourceDefinitionInterface) error { | ||
for _, crdDir := range crdsDir { | ||
// walkCRDs walks the CRDs directory and applies each YAML file. | ||
func walkCRDs(ctx context.Context, crdClient v1.CustomResourceDefinitionInterface) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a question: Does it makes sense to separate filename collection from applying the CRDs? That is to say that we would have logic that accepts the flags and returns a slice of YAML file paths. The logic to apply the CRDs would then accept a slice to YAML file paths. This should make things simpler to test and also allow us to properly de-duplicate if a user specifies a file multiple times, for example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think that makes totally sense. Let me change the code accordingly
Signed-off-by: Tobias Giese <[email protected]>
92553f3
to
4f36d86
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Thanks
if _, err := os.Stat(crdDir); os.IsNotExist(err) { | ||
log.Fatalf("CRDs directory %s does not exist", crdsDir) | ||
log.Fatalf("CRDs directory %s does not exist", filenames) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be:
log.Fatalf("CRDs directory %s does not exist", filenames) | |
log.Fatalf("path does not exist: %s", cdrDir) |
} | ||
|
||
for _, crdDir := range crdsDir { | ||
for _, crdDir := range filenames { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for _, crdDir := range filenames { | |
for _, path := range filenames { |
@@ -84,38 +78,59 @@ func EnsureCRDsCmd() { | |||
log.Fatalf("Failed to create API extensions client: %v", err) | |||
} | |||
|
|||
if err := walkCrdsDir(ctx, client.ApiextensionsV1().CustomResourceDefinitions()); err != nil { | |||
log.Fatalf("Failed to apply CRDs: %v", err) | |||
dirsToApply, err := walkCRDs(recursive, filenames) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dirsToApply, err := walkCRDs(recursive, filenames) | |
pathsToApply, err := collectYamlPaths(recursive, filenames) |
// walkCRDs walks the CRDs directory and applies each YAML file. | ||
// TODO: add unit test for this function. | ||
func walkCRDs(recursive bool, crdDirs []string) ([]string, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// walkCRDs walks the CRDs directory and applies each YAML file. | |
// TODO: add unit test for this function. | |
func walkCRDs(recursive bool, crdDirs []string) ([]string, error) { | |
// collectYAMLPaths processes a list of paths and returns all YAML files. | |
// If `recursive` is specified directories in the list are searched recursively for YAML files. | |
// TODO: add unit test for this function. | |
func collectYAMLPaths(recursive bool, paths []string) ([]string, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that we also need to rename some local variables to better indicate what we are collecting.
// applyCRDsFromFile reads a YAML file, splits it into documents, and applies each CRD to the cluster. | ||
func applyCRDsFromFile(ctx context.Context, crdClient v1.CustomResourceDefinitionInterface, filePath string) error { | ||
// applyCRDs reads a YAML file, splits it into documents, and applies each CRD to the cluster. | ||
func applyCRDs(ctx context.Context, crdClient v1.CustomResourceDefinitionInterface, filePath string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This rename wasn't strictly required, correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it's not required. It was a review finding #58 (comment)
@@ -170,14 +185,19 @@ func applyCRD( | |||
if err != nil { | |||
return fmt.Errorf("create CRD %s: %w", crd.Name, err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: we already add crd.Name
at the caller. Could we just return:
return fmt.Errorf("create CRD %s: %w", crd.Name, err) | |
return fmt.Errorf("create CRD: %w", err) |
(and similarly for Update
below)?
This PR adds a feature to apply single yaml files, not only complete directories.